import java.util.ArrayList;

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import scau.cn.OpenedFileTable;
import scau.cn.OpenedFileTableItem;
import scau.cn.component.abstracts.Disk;
import scau.cn.component.domain.Catalog;
import scau.cn.component.domain.FileN;
import scau.cn.component.util.CatalogOp;
import scau.cn.component.util.FileOp;
import scau.cn.fat.FAT;
import scau.cn.write.os.WriteIntoDisk;

public class FXTest extends Application {
	public static void main(String[] args) {
		launch(args);
	}

	// 你所点击的图片的名字，只要你点了就会触发
	private String cutName = "";
	// 创建新Disk时，Disk的名字
	private String diskName = new String();
	// 创建新Disk时，Disk的属性
	private String diskAttribute = new String();
	private String onlyRead = "只读";
	private String readAndWrite = "读写";
	// --------------------------各种处理器，节点等-------------------------------
	WriteIntoDisk writeIntoDisk = new WriteIntoDisk();
	private CatalogOp catalogOp = new CatalogOp();
	private FileOp fileOp = new FileOp();
	// 绝对的根目录
	Catalog rootCatalog = writeIntoDisk.ReadIn();
	// 当前目录
	Catalog nowCatalog = rootCatalog;

	// 当前节点（用于删除）,对的没错的，这个与上面的nowCatalog重复了，但我不想改了
	Disk nowDisk = null;
	// --------------------------各图片的路径-----------------------------------
	private static String DiskPath = new String("Disk.png");
	private static String CatalogPath = new String("Catalog.png");
	private static String FileNPath = new String("File.png");

	// ---------------------------容器-----------------------------------------
	/**
	 * 焦点容器，没获得一个焦点时，该变量所代表的容器就会变化
	 */
	private Pane cutPane;

	// --------------------------菜单及其子项------------------------------------
	ContextMenu Menu = new ContextMenu();

	/**
	 * 上下文菜单(打开，删除，重命名)，右键展示可选的操作
	 */
	ContextMenu MenuShowOpenOr = new ContextMenu();

	/**
	 * 上下文菜单(新建文件，新建文件夹)，右键展示可选的操作
	 */
	ContextMenu MenuShowCreate = new ContextMenu();
	MenuItem MICreateFile = new MenuItem("新建文件");
	MenuItem MICreateCatalog = new MenuItem("新建文件夹");
	MenuItem MIOpen = new MenuItem("打开");
	MenuItem MIDelete = new MenuItem("删除");
	MenuItem mIChange = new MenuItem("修改");
	// MenuItem MIRename = new MenuItem("重命名");

	// ------------------------事件处理器----------------------------------------
	/**
	 * 点击目录或文件时触发的事件处理器，获得当前窗口的焦点，并在鼠标旁产生一个选项菜单，有打开，删除和重命名 cutPane:当前窗口，是随时变化的
	 */
	EventHandler<ContextMenuEvent> CatalogFileNevent = new EventHandler<ContextMenuEvent>() {
		@Override
		public void handle(ContextMenuEvent event2) {
			// TODO Auto-generated method stu
			MenuShowOpenOr.show(cutPane, event2.getScreenX(), event2.getScreenY());
			event2.consume();

		}
	};

	/**
	 * 点击非目录和文件时触发的事件处理器，获得当前窗口的焦点，并在鼠标旁产生一个选项菜单，有新建文件和新建文件夹 cutPane:当前窗口，是随时变化的
	 */
	EventHandler<ContextMenuEvent> NotCatalogevent = new EventHandler<ContextMenuEvent>() {
		@Override
		public void handle(ContextMenuEvent event) {
			// TODO Auto-generated method stub
			MenuShowCreate.show(cutPane, event.getScreenX(), event.getScreenY());
		}
	};

	@Override
	public void start(Stage primaryStage) {

		BorderPane root = new BorderPane();
		FlowPane pane = new FlowPane();
		cutPane = pane;
		pane.setPadding(new Insets(0, 20, 0, 20));
		pane.setHgap(20);
		pane.setVgap(20);
		// 鼠标点击root时获取FlowPane pane
		root.setOnMouseClicked(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				cutPane = pane;
				nowCatalog = rootCatalog;
				System.out.println("获得rootCatalog " + rootCatalog.getName());
				System.out.println("获得pane " + pane.getParent().getId());
			}
		});

		// ---------------------------设置磁盘的图标--------------------------
		DoubleProperty zoomProperty = new SimpleDoubleProperty(20);
		Label lab = new Label("磁盘");
		Image image = new Image(DiskPath);
		ImageView DiskimageView = new ImageView();
		DiskimageView.setSmooth(false);
		DiskimageView.setFitWidth(zoomProperty.get() * 2);
		DiskimageView.setFitHeight(zoomProperty.get() * 2); // 控制图片的大小
		DiskimageView.setPreserveRatio(false);
		DiskimageView.setImage(image);
		VBox DiskVBox = new VBox();
		// 将磁盘图标装载以个VBox里面
		DiskVBox.getChildren().addAll(DiskimageView, lab);

		// 设置点击磁盘图标时的触发器（统计磁盘的使用以及未使用情况）
		DiskVBox.setOnMouseClicked(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				// MouseButton.PRIMARY.name()左键的名称，所以这里是若果点击左键就触发事件
				if (event.getButton().name().equals(MouseButton.PRIMARY.name())) {
					System.out.println("展示磁盘容量");
					Stage stage5 = new Stage();
					stage5.setAlwaysOnTop(true);
					BorderPane pn = new BorderPane();
					// 已经用了的块数
					int used = 2;
					// 空闲的块数
					int free = 0;
					FAT fat = rootCatalog.getFat();
					for (int i = 2; i < fat.getSpace(); i++) {
						if (fat.getStatus(i) == 0) {
							free++;
						} else {
							used++;
						}
					}
					HBox h1 = new HBox();
					Label la1 = new Label("磁盘块总量为：128");
					h1.getChildren().addAll(la1);
					HBox h2 = new HBox();
					Label la2 = new Label("剩余磁盘量" + String.valueOf(free));
					h2.getChildren().addAll(la2);
					HBox h3 = new HBox();
					Label la3 = new Label("占用的磁盘量" + String.valueOf(used));
					h3.getChildren().addAll(la3);
					VBox ss = new VBox();
					DiskVBox.setSpacing(20);
					ss.getChildren().addAll(h1, h2, h3);
					// VBox ss置于pn的顶部
					pn.setTop(ss);

					// ------------------------下面就是那个圆形的统计图------------------
					PieChart.Data d1 = new PieChart.Data("占用磁盘", used);
					PieChart.Data d2 = new PieChart.Data("空闲磁盘", free);
					ObservableList<PieChart.Data> datelistDatas = FXCollections.observableArrayList();
					datelistDatas.addAll(d1, d2);
					PieChart pieChart = new PieChart(datelistDatas);

					// 将统计图放置在中间
					pn.setCenter(pieChart);

					Scene scene = new Scene(pn, 400, 400);
					stage5.setScene(scene);
					stage5.setTitle("磁盘管理");
					stage5.show();
				}
			}
		});

		// FlowPan pane装载DiskVBox
		pane.getChildren().add(DiskVBox);
		// 最底层容器装载FlowPan pane
		root.getChildren().add(pane);
		// 生成当前图层（即当前目录）的所有子目录，文件图标
		CreateAllIma(pane);

		// 设置选择打开选项时的操作
		MIOpen.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				// TODO Auto-generated method stub
				// 创建新的stage 从event里面获得按钮
				String name = cutName;
				ArrayList<Disk> lists = nowCatalog.getComponent();
				for (int i = 0; i < lists.size(); i++) {
					Disk node = lists.get(i);
					if (node.getName().equals(name)) {
						System.out.println("存在");
						if (node instanceof Catalog) {
							Stage secondStage = new Stage();
							secondStage.setAlwaysOnTop(true);
							secondStage.setTitle(node.findPath());
							FlowPane pane1 = new FlowPane();
							pane1.setPadding(new Insets(0, 20, 0, 20));
							pane1.setHgap(20);
							pane1.setVgap(20);
							// 设置这个容器点击非文件，非目录时所出现选项
							pane1.addEventHandler(ContextMenuEvent.ANY, NotCatalogevent);
							pane1.setOnMouseClicked(new EventHandler<MouseEvent>() {
								@Override
								public void handle(MouseEvent event) {
									cutPane = pane1;
									nowCatalog = (Catalog) node;
									// 当点击时获得当前Catalog目录
									// nowCatalog = rootCatalog.getCatalogFromRoot(secondStage.getTitle());
									System.out.println("当前窗口时获得对应的Catalog对象" + nowCatalog.findPath());
								}
							});
							nowCatalog = (Catalog) node;
//							//下面这个if基本上不会用到。
//							if (nowCatalog != null && nowCatalog.findPath().equals(node.findPath())) {
//								nowCatalog = catalogOp.enterCatalog(node.getName(), nowCatalog);
//							}
							CreateAllIma(pane1);
							Scene secondScene = new Scene(pane1, 300, 200);
							secondStage.setScene(secondScene);
							secondStage.show();
						} else {
							Stage secondStage1 = new Stage();
							// 该窗口的题目就是文件的路径
							secondStage1.setTitle(node.findPath());
							secondStage1.setAlwaysOnTop(true);
							// 自动打开文件
							String txtString = fileOp.readFile(node.getName(), nowCatalog);
							BorderPane pane2 = new BorderPane();
							TextArea area = new TextArea();
							area.setWrapText(true);
							System.out.println("文件内容为" + txtString);
							area.setText(txtString);
							Pane pppPane = new Pane();
							System.out.println("该文件属性为" + node.getOpType());
							if (node.getOpType() == 1) {
								Button button = new Button("保存");
								button.setOnMouseClicked(new EventHandler<MouseEvent>() {
									@Override
									public void handle(MouseEvent event) {
										String content = area.getText();
										try {
											fileOp.writeFile(node.getName(), (Catalog) node.getParent(), content);
											System.out.println("文件写入" + content);
										} catch (Exception e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										}
										// 将根目录序列化写进文件
										writeIntoDisk.WriteIn(rootCatalog);
										secondStage1.close();

									}
								});
								pppPane.getChildren().add(button);
								pane2.setBottom(pppPane);
							}
							pane2.setCenter(area);
							Scene secondScene = new Scene(pane2);
							secondStage1.setScene(secondScene);
							secondStage1.show();
							/**
							 * 定义窗口关闭事件 当窗口关闭时关闭文件
							 */
							secondStage1.setOnCloseRequest((WindowEvent event1) -> {
								try {
									OpenedFileTable oft = OpenedFileTable.getOpenedFileTable();
									System.out.println("窗口关闭事件，临关闭前当前已打开文件数： " + oft.getListOfItem().size());
									fileOp.closeFile(node.getName(), (Catalog) node.getParent());
									System.out.println("窗口关闭事件，临关闭后当前已打开文件数： " + oft.getListOfItem().size());
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							});
						}
						break;
					}
				}

			}
		});

		// 设置点击删除时的事件
		MIDelete.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				for (Node a : cutPane.getChildren()) {
					VBox vv = (VBox) a;
					Label as = (Label) vv.getChildren().get(1);
					String aString2 = as.getText();
					if (aString2.equals(cutName)) {
						// cutPane在fileUI那里会自动获取所点击的对象
						cutPane.getChildren().remove(a);
						// NowDisk在fileUI那里会自动获取所点击的对象
						if (nowDisk instanceof Catalog) {
							catalogOp.deleteCatalog((Catalog) nowDisk);
						} else if (nowDisk instanceof FileN) {
							try {
								fileOp.deleteFile(nowDisk.getName(), (Catalog) nowDisk.getParent());
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
						// 写进文档
						writeIntoDisk.WriteIn(rootCatalog);
						break;
					}
				}

			}
		});

		// 设置点击修改属性时的事件
		mIChange.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				Stage secondStage3 = new Stage();
				secondStage3.getIcons()
						.add(new Image(Thread.currentThread().getContextClassLoader().getResourceAsStream(FileNPath)));
				secondStage3.setTitle("修改文件属性");
				secondStage3.setWidth(200);
				secondStage3.setAlwaysOnTop(true);
				BorderPane pane3 = new BorderPane();
				ChoiceBox<String> cb = new ChoiceBox<>();
				cb.setItems(FXCollections.observableArrayList(onlyRead, readAndWrite));
				Label label2 = new Label("请输入属性");
				// TextField field2 = new TextField();
				VBox qq = new VBox();
				qq.getChildren().addAll(label2, cb);
				HBox hBox = new HBox();
				hBox.setAlignment(Pos.CENTER);
				Button qButton = new Button("确认");
				hBox.getChildren().add(qButton);
				pane3.setCenter(qq);
				pane3.setBottom(hBox);
				Scene secondScene = new Scene(pane3);
				secondStage3.setScene(secondScene);
				secondStage3.show();
				qButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
					@Override
					public void handle(MouseEvent event) {
						// TODO Auto-generated method stub
						int attribute1 = 9;
						if (onlyRead.equals(cb.getValue())) {
							//这个等于0是为了兼容Disk的setOpType
							attribute1 = 0;
							System.out.println("修改了文件属性" + attribute1);
						} else if (readAndWrite.equals(cb.getValue())) {
							//这个等于1是为了兼容Disk的setOpType
							attribute1 = 1;
							System.out.println("修改了文件属性" + attribute1);
						}
						nowDisk.setOpType(attribute1);
						writeIntoDisk.WriteIn(rootCatalog);
						secondStage3.close();
					}
				});
			}
		});

		/**
		 * 定义创建新文件事件
		 */
		MICreateFile.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				Stage secondStage3 = new Stage();
				secondStage3.getIcons()
						.add(new Image(Thread.currentThread().getContextClassLoader().getResourceAsStream(FileNPath)));
				secondStage3.setTitle("新建文件");
				secondStage3.setWidth(200);
				secondStage3.setAlwaysOnTop(true);
				BorderPane pane3 = new BorderPane();
				Label label = new Label("请输入名字");
				TextField field = new TextField();

				ChoiceBox<String> cb = new ChoiceBox<>();
				cb.setMinWidth(field.getWidth());
				cb.setItems(FXCollections.observableArrayList(onlyRead, readAndWrite));
				Label label2 = new Label("请输入属性");
				// TextField field2 = new TextField();
				VBox qq = new VBox();
				qq.getChildren().addAll(label, field);
				qq.getChildren().addAll(label2, cb);
				HBox hBox = new HBox();
				hBox.setAlignment(Pos.CENTER);
				Button qButton = new Button("确认");
				hBox.getChildren().add(qButton);
				pane3.setCenter(qq);
				pane3.setBottom(hBox);
				Scene secondScene = new Scene(pane3);
				secondStage3.setScene(secondScene);
				secondStage3.show();
				qButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
					@Override
					public void handle(MouseEvent event) { // TODO Auto-generated method stub
						diskName = field.getText();
						int attribute1 = 9;
						if (onlyRead.equals(cb.getValue())) {
							System.out.println("创建了只读文件");
							attribute1 = 1;
						} else if (readAndWrite.equals(cb.getValue())) {
							System.out.println("创建了读写文件");
							attribute1 = 4;
						}
						FileN newFile;
						try {
							newFile = FileOp.createFile(diskName, (byte) attribute1, nowCatalog);
							System.out.println("文件属性是" + attribute1);
							VBox vBox = fileUI(newFile);
							cutPane.getChildren().add(vBox);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						writeIntoDisk.WriteIn(rootCatalog);
						secondStage3.close();
					}
				});
			}
		});

		/**
		 * 定义创建新目录事件
		 */
		MICreateCatalog.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				Stage secondStage3 = new Stage();
				BorderPane pane3 = new BorderPane();
				Label label = new Label("请输入名字");
				TextField field = new TextField();
				Label label2 = new Label("请选择属性");
				ChoiceBox<String> cb = new ChoiceBox<>();
				cb.setMinWidth(field.getWidth());
				cb.setItems(FXCollections.observableArrayList(onlyRead, readAndWrite));

				VBox qq = new VBox();
				qq.getChildren().addAll(label, field);
				qq.getChildren().addAll(label2, cb);
				HBox hBox = new HBox();
				hBox.setAlignment(Pos.CENTER);
				Button qButton = new Button("确认");
				hBox.getChildren().add(qButton);
				pane3.setCenter(qq);
				pane3.setBottom(hBox);
				Scene secondScene = new Scene(pane3);
				secondStage3.setScene(secondScene);
				secondStage3.show();
				qButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
					@Override
					public void handle(MouseEvent event) {
						diskName = field.getText();
						int attribute1 = 0;
						if (onlyRead.equals(cb.getValue())) {
							//这里不是opType，而是二进制的attribute
							attribute1 = 9; //0b00001001
						} else if (readAndWrite.equals(cb.getValue())) {
							attribute1 = 12; //0b00001100
						}
						Catalog newCatalog;
						try {
							System.out.println(nowCatalog.getComponent().size());
							newCatalog = catalogOp.createCatalog(diskName, (byte) attribute1, (Catalog) nowCatalog);
							System.out.println(nowCatalog.getComponent().size());
							VBox vBox = fileUI(newCatalog);
							cutPane.getChildren().add(vBox);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						writeIntoDisk.WriteIn(rootCatalog);
						secondStage3.close();
					}
				});
			}
		});

		MenuShowCreate.getItems().addAll(MICreateFile, MICreateCatalog);
		MenuShowOpenOr.getItems().addAll(MIOpen, MIDelete, mIChange);
		root.addEventHandler(ContextMenuEvent.ANY, NotCatalogevent);
		Scene scene = new Scene(root);
		scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
		primaryStage.setScene(scene);
		primaryStage.setMaximized(true);
		primaryStage.show();
	}

	/**
	 * 生成当前pane（即当前目录）中的所有图标（文件目录） 这里我改了一下名字，这个函数就是原来的upsetUI2，并且我把upsetUI删除了
	 * 
	 * @param pane
	 */
	private void CreateAllIma(Pane pane) {
//		System.out.println("CreateAllIma中nowCatalog的路径" + nowCatalog.findPath() + " " + nowCatalog.getParent());
		ArrayList<Disk> lists = nowCatalog.getComponent();
		for (int i = 0; i < lists.size(); i++) {
			Disk node = lists.get(i);
			VBox vBox = fileUI(node);
			pane.getChildren().add(vBox);

		}
	}

	// 创造一个文件或文件夹所对应的图标
	public VBox fileUI(Disk node) {
		DoubleProperty zoomProperty = new SimpleDoubleProperty(20);
		Label lab = new Label(node.getName());
		Image image = null;
		// 生成图片
		if (node instanceof FileN) {
			image = new Image(FileNPath);
		} else if (node instanceof Catalog) {
			image = new Image(CatalogPath);
		}
		// 用ImageView状态图片
		ImageView imageView = new ImageView();
		imageView.setSmooth(false);
		imageView.setFitWidth(zoomProperty.get() * 2);
		imageView.setFitHeight(zoomProperty.get() * 2); // 控制图片的大小
		imageView.setPreserveRatio(false);
		imageView.setImage(image);
		imageView.setMouseTransparent(true);

		// 用VBox装载上面的组件
		VBox vBox = new VBox();
		vBox.getChildren().addAll(imageView, lab);
		// 设置事件处理器
		vBox.addEventHandler(ContextMenuEvent.ANY, CatalogFileNevent);
		// 设置点击时的操作，获取图标的名字并赋值给v全局变量cutName
		// 注意，这里无论你是否还在这个函数，只要你点了，cutName就会被赋值
		vBox.setOnMouseClicked(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				nowDisk = node;
				cutPane = (Pane) vBox.getParent().getParent();
				System.out.println("fileUI获得所点击的Disk: " + nowDisk.findPath());
				VBox vv = (VBox) event.getTarget();
				// 这个1是个大坑。所以上面的vBox.getChildren().addAll(imageView, lab);
				// 中的lab必须是第二个添加
				Label a = (Label) vv.getChildren().get(1);
				String aString2 = a.getText();
				System.out.println("fileUI: " + aString2);
				cutName = aString2;
			}
		});
		return vBox;
	}

}
